Skip to content

feat(audit): promote outcome / ip / userAgent to first-class AuditEvent fields#19

Merged
jlc488 merged 1 commit into
mainfrom
feat/audit-event-firstclass-fields
May 30, 2026
Merged

feat(audit): promote outcome / ip / userAgent to first-class AuditEvent fields#19
jlc488 merged 1 commit into
mainfrom
feat/audit-event-firstclass-fields

Conversation

@jlc488

@jlc488 jlc488 commented May 27, 2026

Copy link
Copy Markdown
Contributor

Follow-up #1/5 to the contract-gap series. Closes the SPI debt #15 flagged: that PR added the columns and a metadata-map fallback so publishers could record outcome / ip / userAgent without breaking the old SPI; this PR makes them first-class on the event record itself.

Summary

API additions

  • AuditOutcome enum in audit-api: SUCCESS / FAILURE. Mirrors the values stored in platform_audit_log.outcome and surfaced in the admin UI.
  • AuditEvent record gains outcome, ip, userAgent fields. The canonical constructor accepts them; the original 5-arg constructor is preserved as a backward-compatible delegation so every existing caller still compiles unchanged.
  • AuditEvent.builder() — typed fluent builder for the now-eight-field record, keeping publish-sites readable as the field count grows.

Persistence

  • AuditLogService.record reads outcome / ip / userAgent directly from the event record, falling back to the metadata-map convention from feat(audit-logs): paging + filters + outcome/ip/userAgent + field rename #15 when the first-class fields are null. Net effect: legacy publishers keep working, new publishers use the builder.
  • Outcome strings (from either source) are normalised through AuditOutcome.valueOf, so garbage values land as NULL — the response layer then treats them as SUCCESS, matching the pre-existing "NULL == SUCCESS" default.

Test plan

  • ./gradlew build green (55 tasks; all tests pass — no schema change, no breaking change to publishers)
  • Manual: trigger a publisher that uses the new builder; confirm the event row carries the outcome/ip/userAgent in their dedicated columns (not the metadata JSON)

…nt fields

Follow-up to #15. That PR added the columns and the metadata-map
fallback so publishers could record outcome/ip/userAgent without
breaking the old SPI; this PR makes them first-class on the event
record itself so new publishers don't have to use the metadata map.

API additions
-------------
- New AuditOutcome enum in audit-api: SUCCESS / FAILURE. Mirrors
  the values stored in platform_audit_log.outcome and surfaced in
  the admin UI's Audit Logs page.
- AuditEvent record gains outcome, ip, userAgent fields. The
  canonical constructor accepts them; the original 5-arg
  constructor is kept as a backward-compatible delegation so
  every existing caller still compiles.
- New AuditEvent.builder() — typed fluent builder for the eight
  field record, keeping the publish-site readable as the field
  count grows.

Persistence
-----------
- AuditLogService.record now reads outcome/ip/userAgent directly
  from the event record, falling back to the metadata-map
  convention from #15 when the first-class fields are null. Net
  effect: legacy publishers still work unchanged, new publishers
  use the builder.
- Outcome strings (from either source) are normalised through
  AuditOutcome.valueOf so garbage values land as NULL — the
  response layer then treats them as SUCCESS, matching the
  pre-existing default-on-null behaviour.
@jlc488
jlc488 merged commit 75da83d into main May 30, 2026
1 check passed
@jlc488
jlc488 deleted the feat/audit-event-firstclass-fields branch May 30, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant